# Unit Statistics Mod
#  by
# Teg_Navanis
# based on Kill List Mod by Roger Bacon

import RandomNameUtils
import NexusNameUtils
import Numsort
import UnitStatisticsTools
from UnitStatisticsDefines import *

	
## globals

objUnitStatisticsTools = UnitStatisticsTools.UnitStatisticsTools()



class UnitStatisticsUtils:

	# Launches the popup (strStatType is either "unit" or "player")
	def launchPopup(self, objUnit, strStatType):
		
		# Create the popup
		popup = PyPopup.PyPopup()
		# TODO - CHANGE THIS CODE TO CENTER POPUP
		if (strStatType == "unit"):		
			popup.setHeaderString("Unit Statistics: %s" %(objUnit.getNameNoDesc()))
			popup.setBodyString(objUnitStatisticsTools.getUnitStatisticsString(objUnit))
		elif (strStatType == "player"):		
			popup.setHeaderString("Player statistics")
			popup.setBodyString(self.getPlayerStatisticsString(gc.getGame().getActivePlayer()))
		popup.setPosition(100,100)
		popup.setSize(700,500)
		popup.launch()

	# Initializes UnitStats if there is something wrong with the game (if it hasn't been started
	# with UnitStats running for example).	
	def onLoadGame(self):
		
		unitList = []
		
		if (g_bTrackAllPlayers or gc.getGame().isGameMultiPlayer()):
			for iPlayer in range(gc.getMAX_PLAYERS()):
				if (gc.getPlayer(iPlayer).isEverAlive()):
					pyPlayer = PyPlayer(iPlayer)
					unitList = unitList + pyPlayer.getUnitList()	
		else:
			unitList = PyPlayer(gc.getGame().getActivePlayer()).getUnitList()
			
		for objUnit in unitList:
			self.setupUnitStats(objUnit)

	def onGameStart(self):
		
		if (g_bTrackAllPlayers or gc.getGame().isGameMultiPlayer()):
			for iPlayer in range(gc.getMAX_PLAYERS()):
				if (gc.getPlayer(iPlayer).isEverAlive()):
					if(sdObjectExists("UnitStats", gc.getPlayer(iPlayer)) == False and gc.getPlayer(iPlayer) != None):
						sdObjectInit("UnitStats", gc.getPlayer(iPlayer), PlayerStatsData)


	# Begins logging the unit information.
	def beginLoggingUnit(self, strCityName, objUnit, iPlayerID):
	
		# Get the currently active player
		objPlayer = gc.getPlayer(objUnit.getOwner())
		
		# Return immediately if the city name passed in is invalid, if this 
		# does happen then the unit information will still be logged through
		# the logUnitCreated method. 
		if(strCityName == None):
			return
			
		# Return immediately if the city name passed in is empty, if this 
		# does happen then the unit information will still be logged through
		# the logUnitCreated method. 
		if(strCityName == ""):
			return		
			
		# Return immediately if the unit passed in is invalid
		if(objUnit == None):
			return
			
		# Return immediately if the player ID passed in is invalid
		if(objPlayer == None):
			return

		# Get the game clock string
		strGameClock = self.getCurrentGameClockString(objUnit.getOwner())
		
		# Construct the unit built message
		newBuiltMessage = "%s: %s " + localText.getText("TXT_KEY_UNITSTATS_BUILTIN", ()) + " %s \n"
		newBuiltMessage = newBuiltMessage %(strGameClock, gc.getUnitInfo(objUnit.getUnitType()).getDescription(), strCityName)

		# This call is used instead of updateUnitLog since using 
		# updateUnitLog will cause a double entry when the unit is built.
		sdObjectSetVal("UnitStats", objUnit, LIST, newBuiltMessage)
		
		# Log Experience of the unit.
		
		sdObjectSetVal("UnitStats", objUnit, EXPERIENCE, objUnit.getExperience())
		
		# Log Experience for player stats.
		sdObjectSetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), EXPERIENCE, sdObjectGetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), EXPERIENCE) + objUnit.getExperience())
		
		#This checks the unit for high scores (experience)
		if (g_bTrackHighScore):
			objUnitStatisticsTools.checkHighScoresCurrentUnit([EXPERIENCE], objUnit)


	# Logs the creation of a unit by the player represented by the iPlayerID
	def logUnitCreation(self, objUnit, iPlayerID):

		# Get the currently active player
		objPlayer = gc.getPlayer(objUnit.getOwner())

		# Return immediately if the unit passed in is invalid
		if(objUnit == None):
			return
			
		# Return immediately if the player ID passed in is invalid
		if(objPlayer == None):
			return

		if (sdObjectExists("UnitStats", objUnit) == False):
			self.setupUnitStats(objUnit)

		print "unit created"
		UnitID = str(objUnit.getID())+ "X" + str(objUnit.getOwner())
		print UnitID

		# If the unit doesn't have a name already then try to give them one	
		if(len(objUnit.getNameNoDesc()) == 0):
		
			# Get the next possible unit name
			strUnitName = self.getNextUnitName(objUnit)

			# If the possible unit name is valid then set it as the unit's name
			if(strUnitName != None and len(strUnitName) > 0):
				objUnit.setName(strUnitName)

		# Save the new units location
		sdObjectSetVal("UnitStats", objUnit, PLOT, [objUnit.getX(), objUnit.getY()])
		
		# Save start turn, start year and starting experience
 		sdObjectSetVal("UnitStats", objUnit, STARTTURN, gc.getGame().getGameTurn())
 		sdObjectSetVal("UnitStats", objUnit, EXPERIENCE, objUnit.getExperience())
		sdObjectSetVal("UnitStats", objUnit, UNITID, str(objUnit.getID()) + "X" + str(objUnit.getOwner()))

		# Get the game clock string
		strGameClock = self.getCurrentGameClockString(objUnit.getOwner())

		# Construct the unit creation message
		newCreatedMessage = "%s: %s " + localText.getText("TXT_KEY_UNITSTATS_CREATED", ()) + "\n"
		newCreatedMessage = newCreatedMessage %(strGameClock, gc.getUnitInfo(objUnit.getUnitType()).getDescription())
		
		# log the creation message for the unit.
		self.updateUnitLog(objUnit, newCreatedMessage)


		return


	# Logs the movement of a unit
	def logUnitMove(self, objUnit):
		
		iPlayerID = objUnit.getOwner()
		
		# Return immediately if the unit passed in is invalid
		if(objUnit == None):
			return
		
		# Get the amount of moves the unit has made in the past and increment 
		# it by one. 
		iMovementCounter = sdObjectGetVal("UnitStats", objUnit, MOVEMENT_COUNTER) + 1
		
		# Set the new movement count
		sdObjectSetVal("UnitStats", objUnit, MOVEMENT_COUNTER, iMovementCounter)
		
		# Set the player statistics movement count.
		sdObjectSetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), MOVEMENT_COUNTER, sdObjectGetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), MOVEMENT_COUNTER) + 1)
		
		#Check movement high scores
		if (g_bTrackHighScore):
			objUnitStatisticsTools.checkHighScoresCurrentUnit([MOVEMENT_COUNTER], objUnit)


		# If the unit is a transport unit
		if (objUnit.hasCargo()):
			
			# Get the amount of moves the unit has made with cargo in the past and increment 
			# it by one. 		
			sdObjectSetVal("UnitStats", objUnit, CARGO_COUNTER, sdObjectGetVal("UnitStats", objUnit, CARGO_COUNTER) + 1)

			# Set the player statistics cargo movement count.
			sdObjectSetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), CARGO_COUNTER, sdObjectGetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), CARGO_COUNTER) + 1)
	
			#Check cargo high scores
			if (g_bTrackHighScore):
				objUnitStatisticsTools.checkHighScoresCurrentUnit([CARGO_COUNTER], objUnit)


	# Logs the setting of the location of the unit.
	# should this really be called every time a unit moves? Maybe we just need 
	# to fix all of the players units at the end of their upkeep cycle?
	def logUnitLocation(self, objUnit):
		
		# Return immediately if the unit passed in is invalid
		if(objUnit == None):
			return

		iDistanceWarped = 0

		if (sdObjectExists("UnitStats", objUnit) == False):
			self.setupUnitStats(objUnit)

		# Get the old unit location values
		OldPlot = sdObjectGetVal("UnitStats", objUnit, PLOT)
		
		iOldX = OldPlot[0]
		iOldY = OldPlot[1]

		# Get the new unit location values
		iNewX = objUnit.getX()
		iNewY = objUnit.getY()

		# Set the new unit location values	
		sdObjectSetVal("UnitStats", objUnit, PLOT, [iNewX, iNewY])

		# If the old location values and the new location values are valid
		# then calculate the distance between the two
		if(iOldX > 0 and iOldY > 0 and iNewX > 0 and iNewY > 0):
			iDistanceWarped = max(abs(iOldX-iNewX), abs(iOldY-iNewY))

			# Get the old distance warped and add the new distance warped
			newDistanceWarped = sdObjectGetVal("UnitStats", objUnit, WARP) + iDistanceWarped
			
			# Set the new distance warped amount
			sdObjectSetVal("UnitStats", objUnit, WARP, newDistanceWarped)
	
			# Set the player statistics distance warped amount.
			sdObjectSetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), WARP, sdObjectGetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), WARP) + iDistanceWarped)
		
			# Check distance travelled high scores
			if (g_bTrackHighScore):
				objUnitStatisticsTools.checkHighScoresCurrentUnit([WARP], objUnit)

	# Logs everything that is checked every turn (so far, the number of turns fortified)
	def logBeginPlayerTurn(self, argsList):
		iGameTurn, iPlayer = argsList
		pyPlayer = PyPlayer(iPlayer)
		unitList = pyPlayer.getUnitList()
		playerturninformation = sdObjectGetVal("UnitStats", gc.getPlayer(iPlayer), TURNINFORMATION)
		for unit in unitList:
			unitturninformation = sdObjectGetVal("UnitStats", unit, TURNINFORMATION)
			if (unit.fortifyModifier() > 0):
				unitturninformation[0] = unitturninformation[0] + 1
				playerturninformation[0] = playerturninformation[0] + 1
				unitturninformation[1] = unitturninformation[1] + 1
				if (unitturninformation[1] > unitturninformation[2]):
					unitturninformation[2] = unitturninformation[1]
					if (unitturninformation[2] > playerturninformation[2]):
						playerturninformation[2] = unitturninformation[2]	
			else:
				unitturninformation[1] = 0
			objPlotOwner = gc.getPlayer(unit.plot().getOwner())
			objUnitOwner = gc.getPlayer(unit.getOwner())
			if (objPlotOwner != None and objUnitOwner != None):
				if gc.getTeam(objPlotOwner.getTeam()).isAtWar(objUnitOwner.getTeam()):
					unitturninformation[3] = unitturninformation[3] + 1
			sdObjectSetVal("UnitStats", unit, TURNINFORMATION, unitturninformation)
		sdObjectSetVal("UnitStats", gc.getPlayer(iPlayer), TURNINFORMATION, playerturninformation)
		
		objUnitStatisticsTools.checkHighScoresAllUnits(MAXTURNSFORTIFIED, iPlayer, None)
		objUnitStatisticsTools.checkHighScoresAllUnits(COMMANDO, iPlayer, None)
		objUnitStatisticsTools.checkHighScoresAllUnits(TOTALTURNSFORTIFIED, iPlayer, None)
		objUnitStatisticsTools.checkHighScoresAllUnits(UNITAGE, iPlayer, None)

			
	# Logs the goody received event				
	def logUnitGoodyReceived(self, argsList):

		iPlayer, objPlot, objUnit, iGoodyType = argsList
		
		# Get the goody information
		objGoodyInfo = gc.getGoodyInfo(iGoodyType)

		# Return immediately if the unit passed in is invalid
		if(objUnit == None):
			return
			
		# Return immediately if the goody ID passed in is invalid
		if(objGoodyInfo == None):
			return

		# Return immediately if for some reason we haven't been logging the 
		# unit.
		if(sdObjectExists("UnitStats", objUnit) == False):
			self.setupUnitStats(objUnit)

		if (objUnit.getID() != -1):
			# Get the game clock string
			strGameClock = self.getCurrentGameClockString(iPlayer)
	
			# Construct the unit creation message
			strGoodyDescription = objGoodyInfo.getDescription()
			newGoodyMessage = "%s: %s \n" %(strGameClock, strGoodyDescription)
	
			# log the goody message for the unit.
			self.updateUnitLog(objUnit, newGoodyMessage)

		# log the goody for player statistics:
		sdObjectSetVal("UnitStats", gc.getPlayer(iPlayer), GOODIES, sdObjectGetVal("UnitStats", gc.getPlayer(iPlayer), GOODIES) + 1)

	# Logs the city acquired event				
	def logCityCapture(self, argsList):

		owner,playerType,city,bConquest,bTrade = argsList

		
		for i in range(city.plot().getNumUnits()):
			objUnit = city.plot().getUnit(i)
			if (objUnit.getOwner() == gc.getGame().getActivePlayer()):
				break
		else:
			return


		# Return immediately if for some reason we haven't been logging the 
		# unit.
		if(sdObjectExists("UnitStats", objUnit) == False):
			self.setupUnitStats(objUnit)
		
		# Get the game clock string
		strGameClock = self.getCurrentGameClockString(objUnit.getOwner())

		# Construct the city capture message
		strCaptureDescription = "Captured %s from the %s" %(city.getName(), owner.getCivilizationDescriptionKey())
		newCaptureMessage = "%s: %s \n" %(strGameClock, strCaptureDescription)

		# log the capture message for the unit.
		self.updateUnitLog(objUnit, newCaptureMessage)

		# log the capture for player statistics:
		sdObjectSetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), CAPTURECOUNT, sdObjectGetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), CAPTURECOUNT) + 1)


	# Logs the goody received event				
	def logUnitUpgraded(self, argsList):

		genericArgs = argsList[0][0]
		pOldUnit = genericArgs[0]
		pNewUnit = genericArgs[1]

		# Return immediately if the unit passed in is invalid
		if(pOldUnit == None):
			return
		
		# Return immediately if the unit passed in is invalid
		if(pNewUnit == None):
			return

		# Return immediately if for some reason we haven't been logging the 
		# unit.
		if(sdObjectExists("UnitStats", pNewUnit) == False):
			self.setupUnitStats(objUnit)
			
		# Get the game clock string
		strGameClock = self.getCurrentGameClockString(pNewUnit.getOwner())

		# Construct the unit upgrade message
		newUpgradeMessage = "%s: " + localText.getText("TXT_KEY_UNITSTATS_UPGRADE", ()) +" \n"
		newUpgradeMessage = newUpgradeMessage %(strGameClock, PyInfo.UnitInfo(pOldUnit.getUnitType()).getDescription(), PyInfo.UnitInfo(pNewUnit.getUnitType()).getDescription())

		# log the goody message for the unit.
		self.updateUnitLog(pNewUnit, newUpgradeMessage)

	# Logs the combat results event	(for the loser)
	def logCombatLoss(self, objWinner, objLoser):

		# Return immediately if the objWinner passed in is invalid
		if(objLoser == None):
			return

		objUnit = objLoser

		UnitID = str(objUnit.getID())+ "X" + str(objUnit.getOwner())

		objWinningPlayer = PyPlayer(objWinner.getOwner())
		
		# Return immediately if for some reason we haven't been logging the 
		# unit.
		if(sdObjectExists("UnitStats", objUnit) == False):
			self.setupUnitStats(objUnit)
			
		#Generate the log message

		oddsdata = sdObjectGetVal("UnitStats", objUnit, ODDSDATA)

		iCombatOdds = oddsdata[3]

		highestDefeatOdds = sdObjectGetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), HIGHEST_DEFEAT_ODDS)
		
		
		if (highestDefeatOdds < iCombatOdds and iCombatOdds < 101):
			sdObjectSetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), HIGHEST_DEFEAT_ODDS, iCombatOdds)

		strCombatOdds = str("%.1f%%") %(oddsdata[3])

		victimCivName = objWinningPlayer.getCivilizationAdjective()
			
		# Get the game clock string
		strGameClock = self.getCurrentGameClockString(objLoser.getOwner())

		strAttackOrDefense = oddsdata[4]
		
		strAttackOrDefenseText = localText.getText("TXT_KEY_UNITSTATS_" + strAttackOrDefense, ())

		newCombatMessage = strGameClock + ": " + localText.getText("TXT_KEY_UNITSTATS_KILLED", (victimCivName, gc.getUnitInfo(objWinner.getUnitType()).getDescription(), strCombatOdds)) + " (" + strAttackOrDefenseText + ")\n"

		# log the combat message for the unit.
		self.updateUnitLog(objLoser, newCombatMessage)

	# Logs the combat results event	(for the winner)
	def logCombatResults(self, objWinner, objLoser):
	
		# Return immediately if the objWinner passed in is invalid
		if(objWinner == None):
			return

		objUnit = objWinner

		UnitID = str(objUnit.getID())+ "X" + str(objUnit.getOwner())
		
		objLosingPlayer = PyPlayer(objLoser.getOwner())
		
		# Return immediately if for some reason we haven't been logging the 
		# unit.
		if(sdObjectExists("UnitStats", objUnit) == False):
			self.setupUnitStats(objUnit)
	
		# log the experience of the unit
		oldXP = sdObjectGetVal("UnitStats", objUnit, EXPERIENCE)
		newXP = objUnit.getExperience() - oldXP
		
		if (newXP> 0):
		
			sdObjectSetVal("UnitStats", objUnit, EXPERIENCE, objUnit.getExperience())	
			# log experience for player stats.
			sdObjectSetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), EXPERIENCE, sdObjectGetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), EXPERIENCE) + newXP)


		#Generate the log message

		oddsdata = sdObjectGetVal("UnitStats", objUnit, ODDSDATA)

		iCombatOdds = oddsdata[3]
		
		strCombatOdds = str("%.1f%%") %(oddsdata[3])

		strWinnerHealth = str("%.2f") %(int(objWinner.baseCombatStr()) * float(objWinner.currHitPoints()) / float(objWinner.maxHitPoints()))
		baseStrength = str("%.2f") %(objWinner.baseCombatStr())

		victimCivName = objLosingPlayer.getCivilizationAdjective()
			
		# Get the game clock string
		strGameClock = self.getCurrentGameClockString(objWinner.getOwner())

		strAttackOrDefense = oddsdata[4]
		
		strAttackOrDefenseText = localText.getText("TXT_KEY_UNITSTATS_" + strAttackOrDefense, ())

		newCombatMessage = strGameClock + ": " + localText.getText("TXT_KEY_UNITSTATS_KILL", (victimCivName, gc.getUnitInfo(objLoser.getUnitType()).getDescription(), strWinnerHealth, baseStrength, strCombatOdds)) + " (" + strAttackOrDefenseText + ")\n"

		# log the combat message for the unit.
		self.updateUnitLog(objWinner, newCombatMessage)

		# if this was the luckiest fight of the unit, save the combat odds as the unit's personal high score
		if (iCombatOdds < sdObjectGetVal("UnitStats", objUnit, BESTODDS) or sdObjectGetVal("UnitStats", objUnit, BESTODDS) == -1):
			sdObjectSetVal("UnitStats", objUnit, BESTODDS, iCombatOdds)
			
			#item 2 in the oddsdata list contains a string message that will be displayed on the unit statistics page
			oddsdata[2] = localText.getText("TXT_KEY_UNITSTATS_LUCKIEST_FIGHT", ()) + "\n" + strGameClock + ": " + localText.getText("TXT_KEY_UNITSTATS_KILL", (victimCivName, gc.getUnitInfo(objLoser.getUnitType()).getDescription(), strWinnerHealth, baseStrength, strCombatOdds)) + "\n"

		# store oddsdata list
		sdObjectSetVal("UnitStats", objUnit, ODDSDATA, oddsdata)


		# Check combat high scores
		if (g_bTrackHighScore):
			objUnitStatisticsTools.checkHighScoresCurrentUnit([BATTLECOUNT, BODYCOUNT, EXPERIENCE, BESTODDS, LIFEODDS, AVERAGEODDSHIGHEST, AVERAGEODDSLOWEST], objWinner)

			highestoddsunit = objUnitStatisticsTools.getHSUnit(AVERAGEODDSHIGHEST, "highscore")
			highestodds = objUnitStatisticsTools.getHSVal(AVERAGEODDSHIGHEST, "highscore")
			lowestoddsunit = objUnitStatisticsTools.getHSUnit(AVERAGEODDSLOWEST, "highscore")
			lowestodds = objUnitStatisticsTools.getHSVal(AVERAGEODDSLOWEST, "highscore")

			if (highestoddsunit == UnitID):
				if (sdObjectGetVal("UnitStats", objUnit, AVERAGEODDS) < highestodds):
					objUnitStatisticsTools.checkHighScoresAllUnits(AVERAGEODDSHIGHEST, objUnit.getOwner(), None)

			if (lowestoddsunit == UnitID):
				if (sdObjectGetVal("UnitStats", objUnit, AVERAGEODDS) > lowestodds):
					objUnitStatisticsTools.checkHighScoresAllUnits(AVERAGEODDSLOWEST, objUnit.getOwner(), None)	

	def onUnitLost(self, argsList):
		'Unit Lost'
		objUnit = argsList[0]

		# Get the value whether the unit statistics are deleted or saved
		graveyard = sdObjectGetVal("UnitStats", objUnit, GRAVEYARD)

		# Set the age of the unit
		startturn = sdObjectGetVal("UnitStats", objUnit, STARTTURN)
		unitage = (gc.getGame().getGameTurn() - startturn)
		sdObjectSetVal("UnitStats", objUnit, UNITAGE, unitage)

		# Get an ID string that is unique (unit.getID() isn't unique)
		UnitID = str(objUnit.getID()) + "X" + str(objUnit.getOwner())
		objUnitInfo = PyInfo.UnitInfo(objUnit.getUnitType())
		if ((g_bTrackAllPlayers or gc.getGame().isGameMultiPlayer()) or objUnit.getOwner() == gc.getGame().getActivePlayer()):
			
			#if the unit has been named with the default name-generator, its name is stored in the lostnameslist (unique for each unit type) for re-use.
			if (g_iUnitNaming == 1 and g_bUnitNameRecycling):
				unittypeandowner = objUnitInfo.getDescription() + str(objUnit.getOwner())
				if sdEntityExists("UnitStats", unittypeandowner):
					lostnameslist = sdGetVal("UnitStats", unittypeandowner, LOSTNAMESLIST)
					lostnameslist.append(objUnit.getNameNoDesc())
					sdSetVal("UnitStats", unittypeandowner, LOSTNAMESLIST, lostnameslist)

			#if the unit has been named with the nexus name-generator, its name is stored in the lostnameslist (unique for each unit category) for re-use.
			if (g_iUnitNaming == 3 and g_bUnitNameRecycling):
				unitcategory = 0		
				if (objUnit.getUnitClassType() >= 16 and objUnit.getUnitClassType() <= 43):
					unitcategory= 1
				elif (objUnit.getUnitClassType() >= 45 and objUnit.getUnitClassType() <= 54):
					unitcategory= 2
				elif (objUnit.getUnitClassType() >= 55 and objUnit.getUnitClassType() <= 59):
					unitcategory= 3			
				if (unitcategory != 0):			
					unitcategoryandowner = str(unitcategory) + str(objUnit.getOwner())
					lostnameslist = sdGetVal("UnitStats", unitcategoryandowner, LOSTNAMESLIST)
					lostnameslist.append(objUnit.getNameNoDesc())
					sdSetVal("UnitStats", unitcategoryandowner, LOSTNAMESLIST, lostnameslist)

			#this updates the high scores
			highscorelist = HighScoreTypes.keys()
			graveyard = 0
			for htype in highscorelist:
				if (g_bTrackHighScore):
					#if the lost unit had a high score, check for the new high score holder.
					highscoreunit = objUnitStatisticsTools.getHSUnit(htype, "highscore")
					if (highscoreunit == UnitID):
						graveyard = 1
						objUnitStatisticsTools.checkHighScoresAllUnits(htype, objUnit.getOwner(), objUnit)

						
			objUnitStatisticsTools.cleanGraveYardList(objUnit.getOwner())
			graveyardlist = sdObjectGetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), GRAVEYARDLIST)
			if (graveyardlist.count(0) > 0):
				newplace = graveyardlist.index(0)
				graveyardlist.insert(newplace, UnitID)
				graveyardlist.pop(newplace + 1)
			else:
				graveyardlist.append(UnitID)
			sdObjectSetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), GRAVEYARDLIST, graveyardlist)
			scriptdata = sdObjectGetAll("UnitStats", objUnit)
			objPlot = gc.getMap().plot(graveyardlist.index(UnitID), objUnit.getOwner())
			self.setupUnitStats(objPlot)
			sdObjectSetAll("UnitStats", objPlot, scriptdata)
			sdObjectSetVal("UnitStats", objPlot, UNITTYPE, objUnit.getUnitType())

			PromotionList = []
			for i in range(gc.getNumPromotionInfos()):
				if (objUnit.isHasPromotion(i)):
					PromotionList.append(i)
			sdObjectSetVal("UnitStats", objPlot, PROMOTION_LIST, PromotionList)

			sdObjectWipe("UnitStats", objUnit)


	# Logs the promotion of a unit
	def logUnitPromotion(self, objUnit, iPromotionID):
		
		
		# Get the promotion information
		objPromotionInfo = gc.getPromotionInfo(iPromotionID)

		# Return immediately if the unit passed in is invalid
		if(objUnit == None):
			return
			
		# Return immediately if the promotion ID passed in is invalid
		if(objPromotionInfo == None):
			return

		# Return immediately if for some reason we haven't been logging the 
		# unit.
		if(sdObjectExists("UnitStats", objUnit) == False):
			self.setupUnitStats(objUnit)
			
		# Get the game clock string
		strGameClock = self.getCurrentGameClockString(objUnit.getOwner())
				
		# Construct the unit promotion message
		newPromoMessage = strGameClock + ": " + localText.getText("TXT_KEY_UNITSTATS_PROMOTION", (objPromotionInfo.getDescription(), ())) + "\n"

		# log the promotion message for the unit.
		self.updateUnitLog(objUnit, newPromoMessage)


	# this function is called when a unit is hit
	# iTrack = 0: attacker's and defender's stats are updated.
	# iTrack = 1: only attacker's stats are updated
	# iTrack = 2: only defender's stats are updated
	def onCombatHit(self, argsList, iTrack):
		'Combat Message'

		genericArgs = argsList[0][0]

		attackerUnit = genericArgs[0]
		defenderUnit = genericArgs[1]
		iIsAttacker = genericArgs[2]
		iDamage = genericArgs[3]

		# The numbers in the UpdateList signify the stats that are being updated:
		# 0: damage inflicted
		# 1: damage inflicted while attacking
		# 2: damage inflicted while defending
		# 3: damage suffered
		# 4: damage suffered while attacking
		# 5: damage suffered while defending
		# 6: collateral damage inflicted
		# 7: collateral damage suffered
		# 8: air strike damage inflicted
		# 9: air strike damage suffered
		attackerUpdateList = []
		defenderUpdateList = []
			
		#if the attacking unit is hurt, calculate the damage and define which unit statistics are updated
		if (iIsAttacker == 1):
		
			# Get the damage
			damage = iDamage * float(attackerUnit.baseCombatStr()) / float(attackerUnit.maxHitPoints())
	
			if (iTrack == 0 or iTrack == 1):
				attackerUpdateList.append(3)
		 		attackerUpdateList.append(4)
			if (iTrack == 0 or iTrack == 2):
				defenderUpdateList.append(0)
				defenderUpdateList.append(2)
								
		#if the defending unit is hurt, calculate the damage and define which unit statistics are updated				
		if (iIsAttacker == 0):
			
			# Get the damage
			damage = iDamage * float(defenderUnit.baseCombatStr()) / float(defenderUnit.maxHitPoints())	

			if (iTrack == 0 or iTrack == 1):
				attackerUpdateList.append(0)
		 		attackerUpdateList.append(1)
			if (iTrack == 0 or iTrack == 2):
				defenderUpdateList.append(3)
				defenderUpdateList.append(5)
		
		# Updates the attacker's stat if necessary
		if (len(attackerUpdateList) > 0 and (iTrack == 0 or iTrack == 1)):

			self.damageUpdater(attackerUnit, attackerUpdateList, damage)
			
		# Updates the defender's stat if necessary
		if (len(defenderUpdateList) > 0 and (iTrack == 0 or iTrack == 2)):
			
			self.damageUpdater(defenderUnit, defenderUpdateList, damage)

		if (iIsAttacker == 1):
			# If the attacker dies, update the owner's loss count
			if (attackerUnit.currHitPoints() <= 0 and (iTrack == 0 or iTrack == 1)):
				self.combatcountUpdater(None, ATTACK, 2, attackerUnit.getOwner())

				
			# If the defender wins, check the new combat high scores
			if (attackerUnit.currHitPoints() <= 0 and (iTrack == 0 or iTrack == 2)):
				self.combatcountUpdater(defenderUnit, DEFENCE, 1, defenderUnit.getOwner())
				if (g_bTrackHighScore):
					objUnitStatisticsTools.checkHighScoresCurrentUnit([DAMAGETYPE[0], DAMAGETYPE[2], DAMAGETYPE[3], DAMAGETYPE[5]], defenderUnit)

		if (iIsAttacker == 0):	
			# If the defender dies, update the owner's loss count
			if (defenderUnit.currHitPoints() <= 0 and (iTrack == 0 or iTrack == 2)):
				self.combatcountUpdater(None, DEFENCE, 2, defenderUnit.getOwner())

				
			# If the attacker wins, check the new combat high scores
			if (defenderUnit.currHitPoints() <= 0 and (iTrack == 0 or iTrack == 1)):
				self.combatcountUpdater(attackerUnit, ATTACK, 1, attackerUnit.getOwner())
				if (g_bTrackHighScore):
					objUnitStatisticsTools.checkHighScoresCurrentUnit([DAMAGETYPE[0], DAMAGETYPE[1], DAMAGETYPE[3], DAMAGETYPE[4]], attackerUnit)


	# this function is called when an air unit is intercepted
	# iTrack = 0: attacker's and interceptor's stats are updated.
	# iTrack = 1: only attacker's stats are updated
	# iTrack = 2: only interceptor's stats are updated
	def onAirIntercept(self, argsList, iTrack):
		'Combat Message'

		genericArgs = argsList[0][0]

		attackerUnit = genericArgs[0]
		interceptorUnit = genericArgs[1]
		iIsAttacker = genericArgs[2]
		iDamage = genericArgs[3]

		# The numbers in the UpdateList signify the stats that are being updated:
		# 0: damage inflicted
		# 1: damage inflicted while attacking
		# 2: damage inflicted while defending
		# 3: damage suffered
		# 4: damage suffered while attacking
		# 5: damage suffered while defending
		# 6: collateral damage inflicted
		# 7: collateral damage suffered
		# 8: air strike damage inflicted
		# 9: air strike damage suffered
		attackerUpdateList = []
		interceptorUpdateList = []

		# Updates the units' battle count
		if(iTrack == 0 or iTrack == 2):
			self.combatcountUpdater(interceptorUnit, AIRDEFENCE, 0, interceptorUnit.getOwner())				
		if(iTrack == 0 or iTrack == 1):
			self.combatcountUpdater(attackerUnit, AIRATTACK, 0, attackerUnit.getOwner())				

			
		#if the attacking unit is hurt, calculate the damage and define which unit statistics are updated
		if (iIsAttacker == 1):
			
			# Get the damage
			damage = iDamage * float(attackerUnit.airBaseCombatStr()) / float(attackerUnit.maxHitPoints())

			if (iTrack == 0 or iTrack == 1):
				attackerUpdateList.append(3)
		 		attackerUpdateList.append(4)
			if (iTrack == 0 or iTrack == 2):
				interceptorUpdateList.append(0)
				interceptorUpdateList.append(2)
								
		#if the intercepting unit is hurt, calculate the damage and define which unit statistics are updated				
		if (iIsAttacker == 0):
			# Get the damage
			damage = iDamage * float(interceptorUnit.airBaseCombatStr()) / float(interceptorUnit.maxHitPoints())

			if (iTrack == 0 or iTrack == 1):
				attackerUpdateList.append(0)
		 		attackerUpdateList.append(1)
			if (iTrack == 0 or iTrack == 2):
				interceptorUpdateList.append(3)
				interceptorUpdateList.append(5)
		
		# Updates the attacker's stat if necessary
		if (len(attackerUpdateList) > 0 and (iTrack == 0 or iTrack == 1)):

			self.damageUpdater(attackerUnit, attackerUpdateList, damage)
			
		# Updates the defender's stat if necessary
		if (len(interceptorUpdateList) > 0 and (iTrack == 0 or iTrack == 2)):
			
			self.damageUpdater(interceptorUnit, interceptorUpdateList, damage)

		if (iIsAttacker == 1):
			# If the attacker dies, update the owner's loss count
			if (attackerUnit.currHitPoints() <= 0 and (iTrack == 0 or iTrack == 1)):
				self.combatcountUpdater(None, AIRATTACK, 2, attackerUnit.getOwner())

				
			# If the interceptor wins, check the new combat high scores
			if (attackerUnit.currHitPoints() <= 0 and (iTrack == 0 or iTrack == 2)):
				self.combatcountUpdater(interceptorUnit, AIRDEFENCE, 1, interceptorUnit.getOwner())
				if (g_bTrackHighScore):
					objUnitStatisticsTools.checkHighScoresCurrentUnit([DAMAGETYPE[0], DAMAGETYPE[2], DAMAGETYPE[3], DAMAGETYPE[5]], interceptorUnit)


				# Add a message to the unit log
				strWinnerHealth = str("%.2f") %(int(interceptorUnit.airBaseCombatStr()) * float(interceptorUnit.currHitPoints()) / float(interceptorUnit.maxHitPoints()))
				objLosingPlayer = PyPlayer(attackerUnit.getOwner())
				victimCivName = objLosingPlayer.getCivilizationAdjective()		
				# Get the game clock string
				strGameClock = self.getCurrentGameClockString(interceptorUnit.getOwner())
				baseStrength = str("%.2f") %(interceptorUnit.airBaseCombatStr())

				newCombatMessage = strGameClock + ": " + localText.getText("TXT_KEY_UNITSTATS_KILL", (victimCivName, gc.getUnitInfo(attackerUnit.getUnitType()).getDescription(), strWinnerHealth, baseStrength)) + "\n"
				# log the combat message for the unit.
				self.updateUnitLog(interceptorUnit, newCombatMessage)


		if (iIsAttacker == 0):	
			# If the interceptor dies, update the owner's loss count
			if (interceptorUnit.currHitPoints() <= 0 and (iTrack == 0 or iTrack == 2)):
				self.combatcountUpdater(None, AIRDEFENCE, 2, interceptorUnit.getOwner())

				
			# If the attacker wins, check the new combat high scores
			if (interceptorUnit.currHitPoints() <= 0 and (iTrack == 0 or iTrack == 1)):
				self.combatcountUpdater(attackerUnit, AIRATTACK, 1, attackerUnit.getOwner())
				if (g_bTrackHighScore):
					objUnitStatisticsTools.checkHighScoresCurrentUnit([DAMAGETYPE[0], DAMAGETYPE[1], DAMAGETYPE[3], DAMAGETYPE[4]], attackerUnit)

				# Add a message to the unit log
				strWinnerHealth = str("%.2f") %(int(attackerUnit.airBaseCombatStr()) * float(attackerUnit.currHitPoints()) / float(attackerUnit.maxHitPoints()))
				baseStrength = str("%.2f") %(attackerUnit.airBaseCombatStr())
				objLosingPlayer = PyPlayer(interceptorUnit.getOwner())
				victimCivName = objLosingPlayer.getCivilizationAdjective()	

				# Get the game clock string
				strGameClock = self.getCurrentGameClockString(attackerUnit.getOwner())
				newCombatMessage = strGameClock + ": " + localText.getText("TXT_KEY_UNITSTATS_KILL", (victimCivName, gc.getUnitInfo(interceptorUnit.getUnitType()).getDescription(), strWinnerHealth, baseStrength)) + "\n"
				# log the combat message for the unit.
				self.updateUnitLog(attackerUnit, newCombatMessage)


	
	# this function is called when collateral damage is inflicted
	# iTrack = 0: attacker's and defender's stats are updated.
	# iTrack = 1: only attacker's stats are updated
	# iTrack = 2: only defender's stats are updated
	def onCollateralHit(self, argsList, iTrack):
		'Combat Message'

		genericArgs = argsList[0][0]

		attackerUnit = genericArgs[0]
		defenderUnit = genericArgs[1]
		iDamage = genericArgs[2]

		# The numbers in the UpdateList signify the stats that are being updated:
		# 0: damage inflicted
		# 1: damage inflicted while attacking
		# 2: damage inflicted while defending
		# 3: damage suffered
		# 4: damage suffered while attacking
		# 5: damage suffered while defending
		# 6: collateral damage inflicted
		# 7: collateral damage suffered
		# 8: air strike damage inflicted
		# 9: air strike damage suffered
		attackerUpdateList = []
		defenderUpdateList = []
			
								
		#if the defending unit is hurt, calculate the damage and define which unit statistics are updated				
		damage = iDamage * float(defenderUnit.baseCombatStr()) / float(defenderUnit.maxHitPoints())	
		if (iTrack == 0 or iTrack == 1):
			attackerUpdateList.append(0)
			attackerUpdateList.append(6)
		if (iTrack == 0 or iTrack == 2):
			defenderUpdateList.append(3)
			defenderUpdateList.append(7)
		
		# Updates the attacker's stat if necessary
		if (len(attackerUpdateList) > 0 and (iTrack == 0 or iTrack == 1)):

			self.damageUpdater(attackerUnit, attackerUpdateList, damage)
			
		# Updates the defender's stat if necessary
		if (len(defenderUpdateList) > 0 and (iTrack == 0 or iTrack == 2)):
			
			self.damageUpdater(defenderUnit, defenderUpdateList, damage)

		if (g_bTrackHighScore):
			if (iTrack == 0 or iTrack == 1):
				objUnitStatisticsTools.checkHighScoresCurrentUnit([DAMAGETYPE[6]], attackerUnit)
			if (iTrack == 0 or iTrack == 2):
				objUnitStatisticsTools.checkHighScoresCurrentUnit([DAMAGETYPE[7]], defenderUnit)

	# this function is called when collateral damage is inflicted
	# iTrack = 0: attacker's and defender's stats are updated.
	# iTrack = 1: only attacker's stats are updated
	# iTrack = 2: only defender's stats are updated
	def onAirStrikeHit(self, argsList, iTrack):
		'Combat Message'

		genericArgs = argsList[0][0]

		attackerUnit = genericArgs[0]
		defenderUnit = genericArgs[1]
		iDamage = genericArgs[2]

		# The numbers in the UpdateList signify the stats that are being updated:
		# 0: damage inflicted
		# 1: damage inflicted while attacking
		# 2: damage inflicted while defending
		# 3: damage suffered
		# 4: damage suffered while attacking
		# 5: damage suffered while defending
		# 6: collateral damage inflicted
		# 7: collateral damage suffered
		# 8: air strike damage inflicted
		# 9: air strike damage suffered
		attackerUpdateList = []
		defenderUpdateList = []
			
								
		#if the defending unit is hurt, calculate the damage and define which unit statistics are updated				
		damage = iDamage * float(defenderUnit.baseCombatStr()) / float(defenderUnit.maxHitPoints())	
		if (iTrack == 0 or iTrack == 1):
			attackerUpdateList.append(0)
			attackerUpdateList.append(8)
		if (iTrack == 0 or iTrack == 2):
			defenderUpdateList.append(3)
			defenderUpdateList.append(9)
		
		# Updates the attacker's stat if necessary
		if (len(attackerUpdateList) > 0 and (iTrack == 0 or iTrack == 1)):

			self.combatcountUpdater(attackerUnit, AIRSTRIKE, 0, attackerUnit.getOwner())

			self.damageUpdater(attackerUnit, attackerUpdateList, damage)
			
		# Updates the defender's stat if necessary
		if (len(defenderUpdateList) > 0 and (iTrack == 0 or iTrack == 2)):

			self.combatcountUpdater(defenderUnit, AIRSTRIKE, 1, defenderUnit.getOwner())
			
			self.damageUpdater(defenderUnit, defenderUpdateList, damage)

		if (g_bTrackHighScore):
			if (iTrack == 0 or iTrack == 1):
				objUnitStatisticsTools.checkHighScoresCurrentUnit([DAMAGETYPE[8]], attackerUnit)
			if (iTrack == 0 or iTrack == 2):
				objUnitStatisticsTools.checkHighScoresCurrentUnit([DAMAGETYPE[9]], defenderUnit)


	# this function is called when a unit withdraws from combat
	# iTrack = 0: attacker's and defender's stats are updated.
	# iTrack = 1: only attacker's stats are updated
	# iTrack = 2: only defender's stats are updated
	def onCombatWithdrawal(self, argsList, iTrack):
		'Combat Message'

		genericArgs = argsList[0][0]

		attackerUnit = genericArgs[0]
		defenderUnit = genericArgs[1]


		# Adds a message to the attacker's (withdrawer's) log
		if (iTrack == 0 or iTrack == 1):

			self.combatcountUpdater(attackerUnit, ATTACK, 3, attackerUnit.getOwner())

			oddsdata = sdObjectGetVal("UnitStats", attackerUnit, ODDSDATA)
		
			combatodds = str("%.1f%%") %(oddsdata[3])
	
			strAttackerHealth = str("%.2f") %(int(attackerUnit.baseCombatStr()) * float(attackerUnit.currHitPoints()) / float(attackerUnit.maxHitPoints()))
			strBaseStrength = str("%.2f") %(attackerUnit.baseCombatStr())

			objDefendingPlayer = PyPlayer(defenderUnit.getOwner())

			defenderCivName = objDefendingPlayer.getCivilizationAdjective()
			
			# Get the game clock string
			strGameClock = self.getCurrentGameClockString(attackerUnit.getOwner())

			newWithdrawalMessage = strGameClock + ": " + localText.getText("TXT_KEY_UNITSTATS_OWN_WITHDRAWAL", (defenderCivName, gc.getUnitInfo(defenderUnit.getUnitType()).getDescription(), strAttackerHealth, strBaseStrength, combatodds)) + "\n"

			# log the combat message for the unit.
			self.updateUnitLog(attackerUnit, newWithdrawalMessage)

			# Check some high scores
			if (g_bTrackHighScore):
				objUnitStatisticsTools.checkHighScoresCurrentUnit([BATTLECOUNT, LIFEODDS], attackerUnit)


		# Adds a message to the defender's log
		if (iTrack == 0 or iTrack == 2):

			self.combatcountUpdater(defenderUnit, DEFENCE, 3, defenderUnit.getOwner())

			oddsdata = sdObjectGetVal("UnitStats", defenderUnit, ODDSDATA)
		
			combatodds = str("%.1f%%") %(oddsdata[3])
	
			strDefenderHealth = str("%.2f") %(int(defenderUnit.baseCombatStr()) * float(defenderUnit.currHitPoints()) / float(defenderUnit.maxHitPoints()))
			strBaseStrength = str("%.2f") %(defenderUnit.baseCombatStr())

			objAttackingPlayer = PyPlayer(attackerUnit.getOwner())

			attackerCivName = objAttackingPlayer.getCivilizationAdjective()
					
			# Get the game clock string
			strGameClock = self.getCurrentGameClockString(defenderUnit.getOwner())

			newWithdrawalMessage = strGameClock + ": " + localText.getText("TXT_KEY_UNITSTATS_ENEMY_WITHDRAWAL", (attackerCivName, gc.getUnitInfo(attackerUnit.getUnitType()).getDescription(), strDefenderHealth, strBaseStrength, combatodds)) + "\n"

			# log the combat message for the unit.
			self.updateUnitLog(defenderUnit, newWithdrawalMessage)

			# Check some high scores
			if (g_bTrackHighScore):
				objUnitStatisticsTools.checkHighScoresCurrentUnit([BATTLECOUNT, LIFEODDS], defenderUnit)
				
	def onCombatBegin(self, argsList):
		'Combat Result'	

		genericArgs = argsList[0][0]

		attackerUnit = genericArgs[0]
		defenderUnit = genericArgs[1]
		iDefenderOdds = genericArgs[2]

		Unitl = []
		
		if((g_bTrackAllPlayers or gc.getGame().isGameMultiPlayer()) or attackerUnit.getOwner() == gc.getGame().getActivePlayer()):
			Unitl.append(attackerUnit)
			
		if((g_bTrackAllPlayers or gc.getGame().isGameMultiPlayer()) or defenderUnit.getOwner() == gc.getGame().getActivePlayer()):
			Unitl.append(defenderUnit)
			
		# If at least one unit is to be updated, do the whole loop for each unit that has to be updated.
		if (len(Unitl) > 0):
			for objUnit in Unitl:
				
				UnitID = str(objUnit.getID())+ "X" + str(objUnit.getOwner())

				# get the data for the average odds and the message string displayed
				oddsdata = sdObjectGetVal("UnitStats", objUnit, ODDSDATA)

				if (objUnit == attackerUnit):
					combatodds = iDefenderOdds/10.0
					self.combatcountUpdater(objUnit, ATTACK, 0, objUnit.getOwner())
					oddsdata[4] = "ATTACK"
			
				elif (objUnit == defenderUnit):
					combatodds = 100 - iDefenderOdds/10.0
					self.combatcountUpdater(objUnit, DEFENCE, 0, objUnit.getOwner())
					oddsdata[4] = "DEFENSE"
		
				#item 0 in the oddsdata list is the additive amount of all combat odds
				oddsdata[0] = oddsdata[0] + combatodds
		
				#item 1 in the oddsdata list is the number of fights so far. item 0 / item 1 = average odds
				oddsdata[1] = oddsdata[1] + 1
				
				oddsdata[3] = combatodds

				# store average odds
				sdObjectSetVal("UnitStats", objUnit, AVERAGEODDS, oddsdata[0] / oddsdata[1])
				
				# store oddsdata list
				sdObjectSetVal("UnitStats", objUnit, ODDSDATA, oddsdata)

				# Get the probability that your unit survives.
				lifeodds = sdObjectGetVal("UnitStats", objUnit, LIFEODDS)
				if lifeodds == 101:
					lifeodds = 100
				if (objUnit == attackerUnit):
					lifeodds = lifeodds * (combatodds + (100 - combatodds) * objUnit.withdrawalProbability() / 100) / 100
				elif (objUnit == defenderUnit):
					lifeodds = lifeodds * combatodds / 100		
				sdObjectSetVal("UnitStats", objUnit, LIFEODDS, lifeodds)
	


	# Returns a combination of the current game turn/year depending on the 
	# INI file configuration		
	def getCurrentGameClockString(self, iPlayerID):
		strGameClock = ""
		
		objPlayer = gc.getPlayer(iPlayerID)
		
		# if the player ID passed in is invalid then return only the game turn 
		# regardless if the turn information has been turned off or not.
		
		strTurn = localText.getText("TXT_KEY_UNITSTATS_TURN", ())
		
		if(objPlayer == None):
			strCurrentTurn = gc.getGame().getGameTurn()
			strGameClock = strTurn + " %s" %(strCurrentTurn)
			return strGameClock
			
		# Get the current game turn
		strCurrentTurn = gc.getGame().getGameTurn()

		# Get the current game year
		strCurrentYear = CyGameTextMgr().getInterfaceTimeStr(iPlayerID)			

		if(g_bShowLogTurnInformation and g_bShowLogDateInformation):
			if(g_bShowLogTurnInformationFirst):
				strGameClock = strTurn + " %s (%s)" %(strCurrentTurn, strCurrentYear)
			else:
				strGameClock = "%s (" + strTurn + " %s)" %(strCurrentYear, strCurrentTurn)
		elif(g_bShowLogTurnInformation and not g_bShowLogDateInformation):
				strGameClock = strTurn + " %s" %(strCurrentTurn)
		elif(not g_bShowLogTurnInformation and g_bShowLogDateInformation):
				strGameClock = "%s" %(strCurrentYear)
		else:
			strGameClock = strTurn  +" %s (%s)" %(strCurrentTurn, strCurrentYear)
		
		return strGameClock
		
		
	# Returns the next unit name for the given unit type.
	def getNextUnitName(self, objUnit):
		' strUnitName - the next possible name for the given unit type.'
		
		objUnitInfo = PyInfo.UnitInfo(objUnit.getUnitType())
		strUnitName = None
	
		# Return None if the unit type ID passed in is invalid
		if(objUnit == None):
			return strUnitName

		# Returns if the Name Generator is disabled	
		iUnitTypeCount = 0
		if (g_iUnitNaming == 0):
			return
		
		#starts the built-in Name Generator (Warrior 1, Warrior2...)
		elif (g_iUnitNaming == 1):
			
			# If the unit type information doesn't exist then create it
			unittypeandowner = objUnitInfo.getDescription() + str(objUnit.getOwner())
			if(sdEntityExists("UnitStats", unittypeandowner) == False):

				unitTypeDictionary = { TYPENUMBER : iUnitTypeCount, 
									  				LOSTNAMESLIST: []
									  				}
							
				sdEntityInit("UnitStats", unittypeandowner, unitTypeDictionary)
			
			# if Unit Name Recycling is enabled, we'll check if we have already lost a unit of this type. if we have, re-use the name
			
			if (g_bUnitNameRecycling):		
				lostnameslist = sdGetVal("UnitStats", unittypeandowner, LOSTNAMESLIST)
			
				if (len(lostnameslist) > 0):
				
					#we want to get Warrior 1 before Warrior 2, even if Warrior 2 died first.
					lostnameslistsorted = Numsort.sorted_copy(lostnameslist)
				
					#the unit gets the lowest number possible
					strUnitName = lostnameslistsorted[0]
				
					#the name is deleted from the list, so that it is not used again
					del lostnameslistsorted[0]			
					sdSetVal("UnitStats", unittypeandowner, LOSTNAMESLIST, lostnameslistsorted)
				
					return strUnitName
			
			iUnitTypeCount = sdGetVal("UnitStats", unittypeandowner, TYPENUMBER) + 1

			# Save the new unit type count
			sdSetVal("UnitStats", unittypeandowner, TYPENUMBER, iUnitTypeCount)

			# Build the new unit name
			strUnitName = objUnitInfo.getDescription() + " " + str(iUnitTypeCount)
			
			return strUnitName
		
		# Returns a name with the Random Name Generator
		
		elif (g_iUnitNaming == 2):	
			objUnit.setName(RandomNameUtils.getRandomCivilizationName(objUnit.getCivilizationType()))
			
		elif (g_iUnitNaming == 3):
			unitcategory = 0		

			if (objUnit.getUnitClassType() >= 16 and objUnit.getUnitClassType() <= 43):
				unitcategory= 1

			elif (objUnit.getUnitClassType() >= 45 and objUnit.getUnitClassType() <= 54):
				unitcategory= 2

			elif (objUnit.getUnitClassType() >= 55 and objUnit.getUnitClassType() <= 59):
				unitcategory= 3			
			
			if (unitcategory != 0):	
				unitcategoryandowner = str(unitcategory) + str(objUnit.getOwner())
				if(sdEntityExists("UnitStats", unitcategoryandowner) == False):

					unitTypeDictionary = { LOSTNAMESLIST: [] }
									  									
					sdEntityInit("UnitStats", unitcategoryandowner, unitTypeDictionary)
			
				# if Unit Name Recycling is enabled, we'll check if we have already lost a unit of this type. if we have, re-use the name
			
				if (g_bUnitNameRecycling):
			
					lostnameslist = sdGetVal("UnitStats", unitcategoryandowner, LOSTNAMESLIST)
			
					#if we have lost a unit of this type, re-use its name
			
					if (len(lostnameslist) > 0):
				
						#we want to get Warrior 1 before Warrior 2, even if Warrior 2 died first.
						lostnameslist.sort()
				
						#the unit gets the lowest number possible
						strUnitName = lostnameslist[0]
				
						#the name is deleted from the list, so that it is not used again
						del lostnameslist[0]			
						sdSetVal("UnitStats", unitcategoryandowner, LOSTNAMESLIST, lostnameslist)
				
						return strUnitName
			
			strUnitName = NexusNameUtils.getNexusName(objUnit)		
			return strUnitName	
	
	
	# Updates the log for objUnit with the message
	# passed in through strNewMessage. Returns True if the log was successfully 
	# updated False otherwise
	def updateUnitLog(self, objUnit, strNewMessage):
		' boolean - Returns True if the log was successfully updated False otherwise.'
		
		# Return False immediately if an invalid unit was passed in
		if(objUnit == None):
			return False
						
		# Return False immediately if an invalid new message was passed in
		if(strNewMessage == None):
			return False
			
		# Return False immediately if an empty message was passed in
		if(len(strNewMessage) == 0):
			return False
		
		# Return False immediately if for some reason we haven't been logging
		# the unit.
		if(sdObjectExists("UnitStats", objUnit) == False):
			self.setupUnitStats(objUnit)
			
		# Get the units current log
		strUnitLog = sdObjectGetVal("UnitStats", objUnit, LIST)

		print strUnitLog
		print strNewMessage

		# Add the new message to the unit log
		strUnitLog = strUnitLog + strNewMessage

		# Save the updated unit log.
		sdObjectSetVal("UnitStats", objUnit, LIST, strUnitLog)
		
		return True		
	
	# creates the scriptdata dummy files
	def setupUnitStats(self, objUnit):	

		if (sdObjectExists("UnitStats", objUnit) == False):
			sdObjectInit("UnitStats", objUnit, UnitStatsData)

		if(sdObjectExists("UnitStats", gc.getPlayer(objUnit.getOwner())) == False and gc.getPlayer(objUnit.getOwner()) != None):
			sdObjectInit("UnitStats", gc.getPlayer(objUnit.getOwner()), PlayerStatsData)


		
	# Updates a dictionary in which the number of battles, wins and losses is stored	
	def combatcountUpdater(self, objUnit, AttDef, iType, iOwner):
	
			
		# The combatcount dictionary looks like this: {ATTACK: [iBattles, iKills, iLosses, iWithdrawals], DEFENCE: [iBattles, iKills, iLosses, iWithdrawals], AIRATTACK: [iBattles, iKills, iLosses], AIRDEFENCE: [iBattles, iKills, iLosses], AIRSTRIKE: [iAttacks, iDefences]}
		# combatcount[ATTACK][1] is thus the number of kills in attacks, (combatcount[ATTACK][1] + combatcount[DEFENCE][1]) the total number of kills		
		if (objUnit != None):
			#updates dictionary for unit
			combatcount = sdObjectGetVal("UnitStats", objUnit, COMBATCOUNT)
			combatcount[AttDef][iType] = combatcount[AttDef][iType] + 1
			sdObjectSetVal("UnitStats", objUnit, COMBATCOUNT, combatcount)	
			
		#updates dictionary for player
		combatcount = sdObjectGetVal("UnitStats", gc.getPlayer(iOwner), COMBATCOUNT)
		combatcount[AttDef][iType] = combatcount[AttDef][iType] + 1
		sdObjectSetVal("UnitStats", gc.getPlayer(iOwner), COMBATCOUNT, combatcount)


	# Updates the damage stats for a unit
	def damageUpdater(self, objUnit, updateList, damage):
		
		# Load the player damage stats
		damagestatsplayer = sdObjectGetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), DAMAGESTATS)

		# Load the unit damage stats
		if(objUnit != None):
			damagestatsunit = sdObjectGetVal("UnitStats", objUnit, DAMAGESTATS)

		for updatestat in updateList:
			
			# Updates player damage stat
			damagestatsplayer[updatestat] = damagestatsplayer[updatestat] + damage

			# Updates unit damage stat
			if (objUnit != None):
				damagestatsunit[updatestat] = damagestatsunit[updatestat] + damage

		# Stores unit damage stats
		if (objUnit != None):
			sdObjectSetVal("UnitStats", objUnit, DAMAGESTATS, damagestatsunit)

		# Stores player damage stats
		sdObjectSetVal("UnitStats", gc.getPlayer(objUnit.getOwner()), DAMAGESTATS, damagestatsplayer)
